package service.wx

import org.apache.commons.codec.digest.DigestUtils
import com.alibaba.fastjson.JSON

import org.paic.util.PropHelper

import org.slf4j.Logger
import org.slf4j.LoggerFactory

// 微信公众号服务签名相关
class WxSignature {
	static Logger log = LoggerFactory.getLogger(WxSignature.class)

	final static String CONF_FILE = '/config/wx-messager.properties'

	// access token最后访问时间
	static long lastAccessTimeAccessToken = 0
	// js sdk ticket最后访问时间
	static long lastAccessTimeSign = 0

	// access token 4 auth最后访问时间，与用户有关
	static Map<String, Long> lastAccessTimeAccessToken4Auth = [:]

	static Map cached = [:]

	// wexin access code失效时间为7200 sec
	static long expiredMillis = 1000 * 7000

	// 微信公众号的app配置信息
	static Properties conf = PropHelper.loadProperties(CONF_FILE)
	static void refreshConf(){
		conf = PropHelper.loadProperties(CONF_FILE)
	}

	static String getAccessToken(){
		String accessToken
		boolean isExpired = (System.currentTimeMillis() - lastAccessTimeAccessToken) > expiredMillis
		if(isExpired || !cached.accessToken){
			String urlGetAccessToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${conf.appid}&secret=${conf.secret}"
			def objResult = JSON.parseObject(new URL(urlGetAccessToken).text)
			// 异常
			if(objResult.errcode){
				log.info('error-when-get-access-token - ' + objResult.errmsg)
				return null
			}

			accessToken = objResult.access_token

			cached.accessToken = accessToken
			lastAccessTimeAccessToken = System.currentTimeMillis()

			log.info('get access token from weixin')
		}else{
			accessToken = cached.accessToken

			log.info('get access token from cache')
		}

		accessToken
	}

	// 授权登录后根据code获取access code和openid，需要通过“微信认证”
	static Map getAccessTokenInfo4Auth(String code){
		Map one

		Long tt = lastAccessTimeAccessToken4Auth[code]

		boolean isExpired = !tt || 
			(System.currentTimeMillis() - tt) > expiredMillis

		String cacheKey = 'accessToken4Auth-' + code
		def oldOne = cached[cacheKey]

		if(isExpired || !oldOne){
			cached.remove(cacheKey)

			String urlGetAccessToken = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=${conf.appid}&secret=${conf.secret}&code=${code}&grant_type=authorization_code"
			def objResult = JSON.parseObject(new URL(urlGetAccessToken).text)
			// 异常
			if(objResult.errcode){
				log.info('error-when-get-access-token-4-auth - ' + objResult.errmsg)
				return objResult
			}

			one = objResult

			cached[cacheKey] = objResult
			lastAccessTimeAccessToken4Auth[code] = System.currentTimeMillis()

			log.info('get access token 4 auth from weixin')
		}else{
			one = cached[cacheKey]

			log.info('get access token 4 auth from cache')
		}

		one
	}

	// 生成微信jssdk页面的必要的签名信息
	static Map<String, String> getJsapiInfo(String url){
		boolean isExpired = (System.currentTimeMillis() - lastAccessTimeSign) > expiredMillis
		String ticket
		if(isExpired){
			String accessToken = getAccessToken()
			if(accessToken == null)
				return null

			String urlGetJsapiTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi"
			def objResult = JSON.parseObject(new URL(urlGetJsapiTicket).text)
			// 异常
			if(objResult.errcode){
				log.info('error-when-get-jsapi-ticket - ' + objResult.errmsg)
				return null
			}

			ticket = objResult.ticket

			cached.ticket = ticket
			lastAccessTimeSign = System.currentTimeMillis()

			log.info('get jsapi ticket from weixin')
		}else{
			ticket = cached.ticket
			
			log.info('get jsapi ticket from cache')
		}
		
		String timestamp = '' + System.currentTimeMillis()
		// 到秒
		timestamp = timestamp[0..-4]

		String str = "jsapi_ticket=${ticket}&noncestr=${conf.nonce}&timestamp=${timestamp}&url=${url}"
		String signature = DigestUtils.shaHex(str)

		[signature: signature, timestamp: timestamp, nonce: conf.nonce, appid: conf.appid]
	}
}